﻿Imports System
Imports System.Collections.Generic
Imports System.ComponentModel
Imports System.Text
Imports System.Web
Imports System.Web.UI
Imports System.Web.UI.WebControls
Imports DBase.scafolding.Config
Imports System.Collections.Specialized
'Imports DBase.scafolding.Grid

Namespace DBase.Scafolding.CustomControl

    Public Class TableView
        Inherits WebControl
        Implements INamingContainer

        Dim SortGridLocations As UI.SortControl

        Public Event EventDataBind()

        Public Event EventInsertInLine(id As Dictionary(Of String, Object))
        Public Event EventEditInLine(id As Dictionary(Of String, Object))
        Public Event EventDeleteInLine(id As Dictionary(Of String, Object))
        Public Event EventSelectInLine(id As Dictionary(Of String, Object))

        Public Event EventInsertOutLine()
        Public Event EventEditOutLine(id As Dictionary(Of String, Object))
        Public Event EventDeleteOutLine(id As Dictionary(Of String, Object))

        Public WithEvents GridView As New GridView
        Dim WithEvents PnlSearch As New Panel
        Dim WithEvents DdlField As New DropDownList
        Dim WithEvents TxtSearch As New TextBox
        Dim WithEvents BtnSearch As New Button
        Dim WithEvents LblRowsCount As New Label
        Dim WithEvents BtnReset As New Button
        Dim WithEvents BtnInsertInLine As New Button
        Dim WithEvents BtnInsertOutLine As New Button

        Public Sub New()
            Me.EnsureChildControls()
            Me.InitControl()
        End Sub

        Private _Config As ConfigTable
        Public Property Config() As ConfigTable
            Get
                Return _Config
            End Get
            Set(ByVal value As ConfigTable)
                _Config = value
                SetConfig()
            End Set
        End Property

        Public Overrides Property CssClass() As String
            Get
                Return Me.GridView.CssClass
            End Get
            Set(ByVal value As String)
                Me.GridView.CssClass = value
            End Set
        End Property

        Public Property FiltroGridValue() As Dictionary(Of String, String)
            Get
                Return ViewState("FiltroGridValue")
            End Get
            Set(ByVal value As Dictionary(Of String, String))
                ViewState("FiltroGridValue") = value
            End Set
        End Property

        Private Sub InitControl()

            BtnSearch.Text = "Search"
            BtnReset.Text = "Reset"
            BtnInsertInLine.Text = "InsertInLine"
            BtnInsertOutLine.Text = "InsertOutLine"
            'GridView.EnableViewState = False
            'GridView.ViewStateMode = Web.UI.ViewStateMode.Enabled


        End Sub

        Private Sub SetConfig()

            If Config.AutoFillFileds Then
                Config.FillFields()
            End If



            '-------------------------------------------------------
            ' PULSANTI AZIONI

            BtnInsertInLine.Visible = Me.Config.AddInLine And Me.Config.Editable
            BtnInsertOutLine.Visible = Me.Config.AddOutLine And Me.Config.Editable

            If Me.Config.Editable Then
                If Me.Config.EditInLine Then
                    GridView.Columns.Add(New GridColumn.ColumnEditInLine)
                End If
                If Me.Config.EditOutLine Then
                    GridView.Columns.Add(New GridColumn.ColumnEditOutLine)
                End If
            End If
            If Me.Config.SelectInLine Then
                GridView.Columns.Add(New GridColumn.ColumnSelectRow)
            End If

            '-------------------------------------------------------
            ' FILTER

            For Each Field_Search In Me.Config.Fields
                If Field_Search.ShowInLine Or Field_Search.NotNull Then
                    If Field_Search.InputType = ConfigTable.InputType.Default Then
                        DdlField.Items.Add(New ListItem(Field_Search.LabelName, Field_Search.Name))
                    End If
                End If
            Next
            Me.PnlSearch.Controls.Add(DdlField)
            Me.PnlSearch.Controls.Add(TxtSearch)
            Me.PnlSearch.Controls.Add(New LiteralControl("<br />"))

            'filtri da query string
            If UI.Page.GetValue("filter_table") = Me.Config.Table Then
                DdlField.SelectedValue = UI.Page.GetValue("filter_filed")
                TxtSearch.Text = UI.Page.GetValue("filter_value")
            End If


            Dim qs = Me.Config.DB.GetQuery
            For Each F In Me.Config.Fields
                If F.InputType = ConfigTable.InputType.DropDownList Then
                    Dim d As New DropDownList
                    d.ID = "dds" & F.LabelName

                    Dim Dt As DataTable
                    Dt = qs.Sql(F.ConfigTable.SqlView).ToDataTable

                    d.DataTextField = F.JoinFieldView
                    d.DataValueField = F.JoinFieldLink
                    d.Items.Insert(0, New ListItem("-- Select: " & F.LabelName & " --", ""))

                    For count = 0 To Dt.Rows.Count - 1
                        d.Items.Add(New ListItem(Dt.Rows(count)(F.JoinFieldView), Dt.Rows(count)(F.JoinFieldLink)))
                    Next

                    Me.PnlSearch.Controls.Add(d)
                    Me.PnlSearch.Controls.Add(New LiteralControl("<br />"))
                End If
            Next

            Dim qs2 = Me.Config.DB.GetQuery
            For Each F In Me.Config.Fields
                If F.InputType = ConfigTable.InputType.SearchBox Then
                    Dim Search As New CustomControl.SearchBox
                    Search.ID = "ccs" & F.LabelName
                    Search.field = F
                    Me.PnlSearch.Controls.Add(Search)
                    Me.PnlSearch.Controls.Add(New LiteralControl("<br />"))
                End If
            Next

            Me.PnlSearch.Controls.Add(BtnSearch)
            Me.PnlSearch.Controls.Add(BtnReset)
            Me.PnlSearch.Controls.Add(LblRowsCount)
            Me.PnlSearch.Controls.Add(New LiteralControl("<br />"))
            Me.PnlSearch.Controls.Add(New LiteralControl("<br />"))
            Me.PnlSearch.Controls.Add(BtnInsertInLine)
            Me.PnlSearch.Controls.Add(BtnInsertOutLine)
            Me.PnlSearch.Controls.Add(New LiteralControl("<br />"))
            Me.PnlSearch.Controls.Add(GridView)
            Me.PnlSearch.Controls.Add(New LiteralControl("<br />"))

            '-------------------------------------------------------
            ' COLONNE


            Dim primarykeys As New List(Of String)
            Dim primarykeys_string As String = ""


            Dim AddCol As Boolean

            For Each Field In Me.Config.Fields

                AddCol = Field.ShowInLine Or Field.NotNull

                If Field.Primary Then
                    primarykeys.Add(Field.Name.ToString)
                End If
                If AddCol Then
                    Select Case Field.InputType
                        Case ConfigTable.InputType.Default
                            Me.GridView.Columns.Add(New GridColumn.ColumnTextBox(Field))
                        Case (ConfigTable.InputType.DropDownList)
                            Me.GridView.Columns.Add(New GridColumn.ColumnDropDownList(Me.Config.DB, Field))
                        Case ConfigTable.InputType.CheckBox
                            Me.GridView.Columns.Add(New GridColumn.ColumnCheckBox(Field))
                        Case ConfigTable.InputType.SearchBox
                            Me.GridView.Columns.Add(New GridColumn.ColumnSearchBox(Me.Config.DB, Field))
                        Case ConfigTable.InputType.SearchView
                            Me.GridView.Columns.Add(New GridColumn.ColumnSearchView(Me.Config.DB, Field))
                        Case ConfigTable.InputType.Date
                            Me.GridView.Columns.Add(New GridColumn.ColumnDateTime(Me.Config.DB, Field))
                    End Select

                End If
            Next


        End Sub

        Protected Overrides Sub CreateChildControls()
            Controls.Clear()
            Controls.Add(PnlSearch)

        End Sub

        Private Sub CustomControlEdit_Load(sender As Object, e As System.EventArgs) Handles Me.Load

            SortGridLocations = New UI.SortControl(Me.GridView.UniqueID, Me.ViewState, "", SortDirection.Ascending)
            If Not Me.Page.IsPostBack Then
                Bind()
            End If

        End Sub

        Public Sub Bind()
            Bind(False)
        End Sub

        Private Sub Bind(s As Boolean)

            ' SetConfig()

            If Not Me.Visible Then Exit Sub
            Me.GridView.DataKeyNames = Me.Config.GetPrimary()
            Dim q = Me.Config.DB.GetQuery
            Dim q2 = Me.Config.DB.GetQuery
            Dim DT As New DataTable
            Me.GridView.AutoGenerateColumns = False
            Me.GridView.AllowPaging = True
            Me.GridView.PageSize = Me.Config.GridPageSize
            Dim GridRecordLimit = Me.Config.GridRecord
            Me.GridView.AllowSorting = True
            Me.GridView.ShowHeader = True
            'Me.GridView.CssClass = "table_result_light"
            Me.GridView.AlternatingRowStyle.CssClass = "AlternatingRow"
            Me.GridView.HeaderStyle.CssClass = "Header"


            '------------------------------------
            ' filtri sql

            If Me.FiltroGridValue IsNot Nothing Then
                If Me.Config.Table <> "" Then
                    q.Sql(Me.Config.SqlView).Where(Me.Config.Table & "." & Me.FiltroGridValue.ToList(0).Key, "=", Me.FiltroGridValue.ToList(0).Value)
                Else
                    q.Sql(Me.Config.SqlView).Where(Me.FiltroGridValue.ToList(0).Key, "=", Me.FiltroGridValue.ToList(0).Value)
                End If
            ElseIf Me.Config.SqlView <> "" Then
                q.Sql(Me.Config.SqlView)
            Else
                q.Select("*").From(Me.Config.Table)
            End If

            Dim param As New List(Of Object)

            If TxtSearch.Text <> "" Then

                For Each F In Me.Config.Fields
                    If F.Name = DdlField.SelectedValue Then

                        Select Case F.FieldType
                            Case GetType(String)
                                If Me.Config.Table <> "" Then
                                    q.Where(Me.Config.Table & "." & DdlField.SelectedValue, "LIKE", "%" & TxtSearch.Text & "%")
                                Else
                                    q.Where(DdlField.SelectedValue, "LIKE", "%" & TxtSearch.Text & "%")
                                End If
                            Case Else
                                If Me.Config.Table <> "" Then
                                    q.Where(Me.Config.Table & "." & DdlField.SelectedValue, "=", TxtSearch.Text)
                                Else
                                    q.Where(DdlField.SelectedValue, "=", TxtSearch.Text)
                                End If
                        End Select
                    End If
                Next
            End If

            For Each F In Me.Config.Fields
                If F.InputType = ConfigTable.InputType.DropDownList Then
                    Dim value = UI.Controls.FindControl(Of DropDownList)("dds" & F.LabelName, Me.PnlSearch).SelectedValue
                    If value <> "" Then
                        If Me.Config.Table <> "" Then
                            q.Where(Me.Config.Table & "." & F.Name, "=", value)
                        Else
                            q.Where(F.Name, "=", value)
                        End If
                    End If
                End If
            Next

            For Each F In Me.Config.Fields
                If F.InputType = ConfigTable.InputType.SearchBox Then
                    Dim value = UI.Controls.FindControl(Of CustomControl.SearchBox)("ccs" & F.LabelName, Me.PnlSearch).Value
                    If value <> "" Then
                        If Me.Config.Table <> "" Then
                            q.Where(Me.Config.Table & "." & F.Name, "=", value)
                        Else
                            q.Where(F.Name, "=", value)
                        End If
                    End If
                End If
            Next

            q.Limit(GridRecordLimit)
            DT = Me.SortGridLocations.SortQuery(q).ToDataTable

            q.Reset()

            LblRowsCount.Text = " - Numero righe: " & DT.Rows.Count

            If s = True Then
                GridView.PageIndex = 0
                Dim dataRow As DataRow = DT.NewRow()
                DT.Rows.InsertAt(dataRow, 0)
                GridView.EditIndex = 0
            End If

            Me.GridView.DataSource = DT
            Me.GridView.DataBind()

            '------------------------------------
            ' gestione colonne

            Dim diccol As New Dictionary(Of String, Integer)
            For ct = 0 To Me.GridView.Columns.Count - 1
                diccol.Add(Me.GridView.Columns(ct).ToString, ct)
            Next

            Dim VisCol As Boolean
            For Each Field In Me.Config.Fields

                VisCol = True
                If GridView.EditIndex = -1 And Field.EditOnly Then
                    VisCol = False
                End If
                If GridView.EditIndex <> -1 And Field.ReadOnly Then
                    'VisCol = False
                End If

                If diccol.ContainsKey(Field.LabelName) Then
                    Me.GridView.Columns(diccol(Field.LabelName)).Visible = VisCol
                End If

            Next



            RaiseEvent EventDataBind()

        End Sub

        Protected Overrides Sub Render(ByVal output As HtmlTextWriter)
            For Each c As Object In Controls
                c.RenderControl(output)
            Next
        End Sub

        Private Sub GridView_DataBinding(sender As Object, e As System.EventArgs) Handles GridView.DataBinding
            'SetConfig()
        End Sub

        Protected Sub GridView_RowCommand(sender As Object, e As System.Web.UI.WebControls.GridViewCommandEventArgs) Handles GridView.RowCommand
            'sender.datakeys(e.row.rowindex).value

            Select Case e.CommandName
                Case DBase.Scafolding.Fields.rowCommand.EditOutLine.ToString
                    Dim keys As OrderedDictionary = sender.datakeys(e.CommandSource.dataitemcontainer.rowindex).values
                    Dim PKs As New Dictionary(Of String, Object)
                    For Each id_pk In keys
                        PKs.Add(id_pk.key(), id_pk.value())
                    Next
                    RaiseEvent EventEditOutLine(PKs)
                    Bind()

                Case DBase.Scafolding.Fields.rowCommand.DeleteOutLine.ToString
                    Dim keys As OrderedDictionary = sender.datakeys(e.CommandSource.dataitemcontainer.rowindex).values
                    Dim PKs As New Dictionary(Of String, Object)
                    For Each id_pk In keys
                        PKs.Add(id_pk.key(), id_pk.value())
                    Next
                    RaiseEvent EventDeleteOutLine(PKs)
                    Bind()

                Case DBase.Scafolding.Fields.rowCommand.Select.ToString
                    Dim keys As OrderedDictionary = sender.datakeys(e.CommandSource.dataitemcontainer.rowindex).values
                    Dim PKs As New Dictionary(Of String, Object)
                    For Each id_pk In keys
                        PKs.Add(id_pk.key(), id_pk.value())
                    Next
                    RaiseEvent EventSelectInLine(PKs)

            End Select
        End Sub

        Protected Sub GridView_RowCancelingEdit(sender As Object, e As System.Web.UI.WebControls.GridViewCancelEditEventArgs) Handles GridView.RowCancelingEdit
            GridView.EditIndex = -1
            Bind()
        End Sub

        Protected Sub GridView_RowDeleting(sender As Object, e As System.Web.UI.WebControls.GridViewDeleteEventArgs) Handles GridView.RowDeleting
            Dim q = Me.Config.DB.GetQuery
            q.Delete(Me.Config.Table)
            For Each y In Me.Config.GetPrimary()
                q.Where(y, "=", e.Keys(y))
            Next
            q.ExecuteCommand()
            Bind()

            Dim PKs As New Dictionary(Of String, Object)
            For Each y In Me.Config.GetPrimary()
                PKs.Add(y, e.Keys(y))
            Next
            RaiseEvent EventDeleteInLine(PKs)

        End Sub

        Protected Sub GridView_RowEditing(sender As Object, e As System.Web.UI.WebControls.GridViewEditEventArgs) Handles GridView.RowEditing
            ViewState("Update") = Scafolding.Config.TypeEdit.StatusType.Update
            GridView.EditIndex = e.NewEditIndex
            Bind()
        End Sub

        Protected Sub GridView_PageIndexChanging(sender As Object, e As System.Web.UI.WebControls.GridViewPageEventArgs) Handles GridView.PageIndexChanging
            GridView.PageIndex = e.NewPageIndex
            Bind()
        End Sub

        Protected Sub GridView_RowUpdating(sender As Object, e As System.Web.UI.WebControls.GridViewUpdateEventArgs) Handles GridView.RowUpdating
            EditInLine(ViewState("Update"), Me.Config, Me.GridView, e)
            GridView.EditIndex = -1
            Bind()
        End Sub

        Public Sub EditInLine(type As Config.TypeEdit.StatusType, conf As ConfigTable, g As GridView, e As Object)
            Dim q = Me.Config.DB.GetQuery
            Dim p() As Object = Nothing
            q.Reset()

            Select Case type
                Case TypeEdit.StatusType.Insert
                    q.Insert(Me.Config.Table)
                    If Me.FiltroGridValue IsNot Nothing Then
                        q.InsertValues(Me.FiltroGridValue.ToList(0).Key, Me.FiltroGridValue.ToList(0).Value)
                    End If

                Case TypeEdit.StatusType.Update
                    q.Update(Me.Config.Table)
            End Select

            For Each Field In conf.Fields
                If Field.ShowInLine Or Field.NotNull Then
                    If Not Field.[ReadOnly] Then
                        Select Case Field.InputType
                            Case ConfigTable.InputType.[Default]
                                Dim TxtControl = UI.Grid.GetControl(Of TextBox)(g, e.rowindex, Field.ControlName).Text
                                p = {Field.Name, DBase.Scafolding.Fields.GetConv(Field.FieldType, TxtControl)}
                            Case ConfigTable.InputType.DropDownList
                                If Field.FieldType = GetType(Integer) Then
                                    p = {Field.Name, Utils.Conv.ToInt(UI.Grid.GetControl(Of DropDownList)(g, e.rowindex, Field.ControlName).Text)}
                                Else
                                    p = {Field.Name, UI.Grid.GetControl(Of DropDownList)(g, e.rowindex, Field.ControlName).Text}
                                End If
                            Case ConfigTable.InputType.CheckBox
                                p = {Field.Name, UI.Grid.GetControl(Of CheckBox)(g, e.rowindex, Field.ControlName).Checked}
                            Case ConfigTable.InputType.SearchBox
                                Dim SrcControl = UI.Controls.FindControl(Of CustomControl.SearchBox)(Field.ControlName, g.Rows(e.rowindex))
                                p = {Field.Name, Utils.Conv.ToInt(SrcControl.Value)}
                            Case ConfigTable.InputType.Date
                                Dim DataControl = UI.Controls.FindControl(Of CustomControl.DateTimeEdit)(Field.ControlName, g.Rows(e.rowindex)).Value
                                If DataControl <> "" Then
                                    p = {Field.Name, Utils.Conv.ToDate(DataControl)}
                                Else
                                    p = {Field.Name, Date.Today}
                                End If
                        End Select

                        If Field.InputType <> ConfigTable.InputType.SearchView Then
                            Select Case type
                                Case TypeEdit.StatusType.Insert
                                    q.InsertValues(p)
                                Case TypeEdit.StatusType.Update
                                    q.UpdateValue(p)
                            End Select

                            Select Case type
                                Case TypeEdit.StatusType.Update
                                    For Each y In Me.Config.GetPrimary()
                                        q.Where(y, "=", e.Keys(y))
                                    Next
                            End Select
                        End If

                    End If
                End If
            Next

            If conf.Fields.Where(Function(o) o.ReadOnly = False).Count > 0 Then
                q.ExecuteCommand()
            End If

            Dim PKs As New Dictionary(Of String, Object)
            For Each y In Me.Config.GetPrimary()
                PKs.Add(y, e.Keys(y))
            Next
            Select Case type

                Case TypeEdit.StatusType.Insert

                    Dim LastID As Integer = Fields.GetLastID(Me.Config.DB)
                    Dim PK_add As New Dictionary(Of String, Object)
                    PK_add.Add("ID", LastID)
                    RaiseEvent EventInsertInLine(PK_add)

                Case TypeEdit.StatusType.Update
                    RaiseEvent EventEditInLine(PKs)
            End Select

        End Sub

        Protected Sub GridView_Sorting(sender As Object, e As System.Web.UI.WebControls.GridViewSortEventArgs) Handles GridView.Sorting
            Me.SortGridLocations.Sort(e.SortExpression)
            Me.GridView.PageIndex = 0
            Bind()
        End Sub

        Protected Sub BtnSearch_Click(ByVal sender As Object, ByVal e As EventArgs) Handles BtnSearch.Click
            Me.Visible = True
            Bind()
        End Sub

        Protected Sub BtnReset_Click(sender As Object, e As System.EventArgs) Handles BtnReset.Click
            TxtSearch.Text = ""
            For Each F In Me.Config.Fields
                If F.InputType = ConfigTable.InputType.DropDownList Then
                    UI.Controls.FindControl(Of DropDownList)("dds" & F.LabelName, Me.PnlSearch).SelectedValue = ""
                End If
            Next
            For Each F In Me.Config.Fields
                If F.InputType = ConfigTable.InputType.SearchBox Then
                    UI.Controls.FindControl(Of CustomControl.SearchBox)("ccs" & F.LabelName, Me.PnlSearch).Value = ""
                End If
            Next
            Me.Visible = True
            Bind()
        End Sub

        Protected Sub BtnAdd_Click(sender As Object, e As System.EventArgs) Handles BtnInsertInLine.Click
            ViewState("Update") = Scafolding.Config.TypeEdit.StatusType.Insert
            Me.Visible = True
            Bind(True)
        End Sub

        Protected Sub BtnAdd2_Click(sender As Object, e As System.EventArgs) Handles BtnInsertOutLine.Click
            ViewState("Update") = Scafolding.Config.TypeEdit.StatusType.Insert
            RaiseEvent EventInsertOutLine()
        End Sub

    End Class
End Namespace